callback 是 事件驅動程式設計 (event-driven programming) 中非常強大的功能。
讓 JavaScript 語言能夠將 callback function 作為參數傳遞給其他函數(像是 JS 中的 addEventListener 和 setTimeout)是很有用的。
在 JavaScript 中,callback 被當成 event loop 監督執行已在佇列中進行的程式的指標。
function 被放進 Async Function (非同步函式) 裡作為參數的話, 稱為 callback,這些callback function 會被依序放置在 callback queue 等待執行。
    doX();
    doZ(function() {
      doY();
    });
Result:
    doX() -> doZ() -> doY()
不過 callback 有個缺點就是可能會形成 callback hell (回呼地域)...
回呼地域(callback hell)還有一個比較具體一點的稱呼, 毀滅金字塔(pyramid of doom), 表示層次太深的巢狀 callbacks,過度嵌套太多的 events, callback function 而讓程式架構變得更複雜,難以預測和維護。
    doX(function() {
      doY();
      doZ(function() {
        doQ();
      });
      doF();
    });
    doC();
Result:
    doX() -> doC() -> doY() -> doZ() -> doF() -> doQ()
再看看魔王級別的 callback hell

Credit: https://thecodebarbarian.com/2015/03/20/callback-hell-is-a-myth
是不是滿嚇人的, 不過幸好我們有 Promise, 它可以幫助我們脫離 callback hell 的苦難。
Promise 承諾有兩種: 信守承諾 (fulfill/resolve)、承諾失敗 (reject)。但當在 Promise 承諾的結果展現前,會進入一個不確定到底是成功完成還是失敗的狀態 (pending)。
Promise 是一種契約:
另外, 只能從 Pending 變為 Fulfilled 或 Rejected(沒辦法收回/返回)
舉個簡單的日常生活例子來說, 當你去一家 pizza 餐廳…
Example: 我承諾等一下會回來為您上菜 (by 服務生)
Pending: 等待我的 pizza 上菜…
Fulfilled: Pizza 來了!!
Rejected: 廚房的起司用完了 :(
| function | description | 
|---|---|
| let promiseObj = new Promise(executorFn) | 使用 executorFn 創建一個新的 Promise 物件 | 
| promiseObj.then(onFulfilled, onRejected) | 當 promise 被完成, fulfilled(或是失敗, rejected)時調用 onFulfilled (或是 onRejected) 函數 | 
| promiseObj.catch(callback) | 如果 promise 失敗(或發生錯誤),則調用 callback 函數 | 
    function executorFn(resolve, reject) {
        // ...
        if (conditionMet) {
            resolve(); // Passed by the Promise object
        } else {
            reject(); // Passed by the Promise object
        }
    }
    // 您定義此函數並將其傳遞給 Promise 構造函數 (Promise constructor)